#include "FTBitmapFont.h"
#include "FontAtlas.h"
#include "FTBitmapChar.h"
#include "GLCallBatcher.h"
#include <ft2build.h>
#include <freetype.h>
#include <assert.h>

FTBitmapFont::FTBitmapFont(FontAtlas *fontAtlas) {
	this->fontAtlas = fontAtlas;
	face            = NULL;
    smooth          = true;
}


FTBitmapFont::~FTBitmapFont() {
	ReleaseFace();
}

void FTBitmapFont::ReleaseFace() {
	if (face) {
		FT_Done_Face(face);
		face = NULL;
	}
}

int FTBitmapFont::getWidth(const wchar_t* text) {
	int currX = 0;
	int n = 0;
	unsigned wchar_t c;
    std::map<wchar_t, FTBitmapChar*>::const_iterator iter;
	FT_Vector kerning;
	FT_UInt ixGlyph;
	FT_UInt ixGlyphPrev = 0;
	bool hasKerning = false;
	if (face) {
		hasKerning = FT_HAS_KERNING(face);
	}
	while (text[n] != 0) {
		c = text[n];
		iter = mapBitmapChar.find(c);
		if (iter != mapBitmapChar.end()) {
			if (hasKerning)	{
				// get kerning
				ixGlyph = FT_Get_Char_Index(face, c); 
				if (hasKerning && ixGlyphPrev && ixGlyph) { 
					FT_Get_Kerning(face, ixGlyphPrev, ixGlyph, FT_KERNING_DEFAULT, &kerning); 
					currX += kerning.x >> 6; 
				} 
				ixGlyphPrev = ixGlyph;
			}
			currX += iter->second->getXAdvance();
		}
		n++;
	} 
	return currX;
}

int FTBitmapFont::getCharWidth(wchar_t character) {
    std::map<wchar_t, FTBitmapChar*>::const_iterator iter = mapBitmapChar.find(character);
    if (iter != mapBitmapChar.find(character))
        return iter->second->getXAdvance();
    if (character == ' ')
        return getHeight() * 0.3f;
    return mapBitmapChar.find(L'?')->second->getXAdvance();
}	

int FTBitmapFont::drawString(int x, int y, const wchar_t* text, float scale) {
	fontAtlas->getBatcher()->setAttribs(fontAtlas->getTextureID(), 0xFFFFFF, 1.0f, true, smooth);
	unsigned wchar_t c;
	int currX = x;
	int n = 0;
    std::map<wchar_t, FTBitmapChar*>::const_iterator iter;
	FT_Vector kerning;
	FT_UInt ixGlyph;
	FT_UInt ixGlyphPrev = 0;
	bool hasKerning = false;
	if (face) {
		hasKerning = FT_HAS_KERNING(face); 
	}
	while (text[n] != 0) {
		c = text[n];
		iter = mapBitmapChar.find(c);
		if (iter != mapBitmapChar.end()) {
        label:
			if (hasKerning)	{
				// get kerning
				ixGlyph = FT_Get_Char_Index(face, c); 
				if (hasKerning && ixGlyphPrev && ixGlyph) { 
					FT_Get_Kerning(face, ixGlyphPrev, ixGlyph, FT_KERNING_DEFAULT, &kerning); 
					currX += (kerning.x >> 6) * scale;
				} 
				ixGlyphPrev = ixGlyph;
			}
			iter->second->render(currX, y, scale, fontAtlas->getBatcher());
			currX += iter->second->getXAdvance() * scale;
		} else {
            if (c == ' ') {
                currX += getHeight() * (scale * 0.3f); // SIC: the average width of character in most fonts is usually about this fraction of fonts height.
            } else {
                iter = mapBitmapChar.find(L'?'); // HACK: Show '?' when a letter is not found.
                if(iter != mapBitmapChar.end()) {
                    goto label;
                }
            }
        }
		n++;
	} 
	return currX;
}	

void FTBitmapFont::finishCreating() {
	bool hasKerning = false;
	if (face) {
		hasKerning = FT_HAS_KERNING(face); 
	}
	if (!hasKerning || !fontAtlas->getUseKerning())
		ReleaseFace();
}


